/*
 * Part of knowledge engineering (ke) course work, 2010/11
 */
package se.bth.ke.firstfriend.model.validation;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Path;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import javax.validation.metadata.ConstraintDescriptor;

/**
 *
 * @author markus.goetz
 * @author nico.rehwaldt
 */
public class Validator {
    
    private static HashMap<Class, javax.validation.Validator> validators = new HashMap();
    private static ValidatorFactory factory = Validation.buildDefaultValidatorFactory();

    public static class ValidationResult {
        private Set<ConstraintViolation<Object>> violations = new HashSet();

        public ValidationResult(Set<ConstraintViolation<Object>> violations) {
            this.violations = violations;
        }

        public Set<ConstraintViolation<Object>> getViolations() {
            return violations;
        }

        /**
         * Returns true if no violations are stored in this result
         * @return
         */
        public boolean isEmpty() {
            return violations.isEmpty();
        }

        /**
         * Add the specified message as violation to the user
         * @param message
         */
        public void addViolation(String message) {
            violations.add(new SimpleViolation<Object>(message));
        }
    }

    private static class SimpleViolation<T> implements ConstraintViolation<T> {

        private final String message;

        public SimpleViolation(String message) {
            this.message = message;
        }
        
        @Override
        public String getMessage() {
            return message;
        }

        @Override
        public String toString() {
            return getMessage();
        }

        @Override
        public String getMessageTemplate() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public T getRootBean() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Class<T> getRootBeanClass() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Object getLeafBean() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Path getPropertyPath() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Object getInvalidValue() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public ConstraintDescriptor<?> getConstraintDescriptor() {
            throw new UnsupportedOperationException("Not supported yet.");
        }        
    }

    private static javax.validation.Validator getValidator(Class<?> cls) {
        if (!validators.containsKey(cls)) {
            validators.put(cls, factory.getValidator());
        }
        
        return validators.get(cls);
    }

    public static ValidationResult validate(Object entity) {
        Set<ConstraintViolation<Object>> violations = getValidator(entity.getClass()).validate(entity);
        return new ValidationResult(violations);
    }
}